/*
    Author: Christopher Diggins
    License: MIT Licence 1.0
    Website: http://www.heron-language.com
*/

#ifndef LLSCHEME_VAR_ANALYZER_HPP
#define LLSCHEME_VAR_ANALYZER_HPP

namespace lls
{

	struct VarAnalyzer {
		String var;
		Var* def;
		Undeclare* undef;
		SExpr* lastSimpleUsage; 
		bool bSimpleContext;

		VarAnalyzer(ConstString s) 
			: var(s), def(NULL), undef(NULL), lastSimpleUsage(NULL), bSimpleContext(true)
		{ }
		
		void operator()(SExpr* x) 
		{
			if (IsMatchingVar(x, var)) 
			{
				Assert(def == NULL);
				Assert(undef == NULL);
				def = x->As<Var>();
			}
			else if (IsMatchingUndeclare(x, var)) 
			{
				Assert(def != NULL);
				Assert(undef == NULL);
				undef = x->As<Undeclare>();
			}
			else if (IsGet(x, var))
			{
				Assert(def != NULL);
				Assert(undef == NULL);
				
				// This identifies a place where the value can be retrieved, 
				// and undeclared simultaneously.
				if (bSimpleContext)
					lastSimpleUsage = x;
				else
					lastSimpleUsage = NULL;
			}
			else if (IsAtom(x, var)) 
			{
				lastSimpleUsage = NULL;
			}
			else if (IsSpecialConstruct(x))
			{
				bool bSaveContext = bSimpleContext;
				bSimpleContext = false;
				x->ForEach(*this);
				bSimpleContext = bSaveContext;
			}
			else 
			{
				x->ForEach(*this);
			}
		}

		void RemoveVar() {
			def->DeleteSelf();
			undef->DeleteSelf();
			def = NULL;
			undef = NULL;
		}
	};
}

#endif
